using System.Collections;
using System.Collections.Generic;
using UnityEngine;
namespace BehTree{
public class Driver : MonoBehaviour
{
    class TreeNode
    {
        public NodeBase curNode;
        public List<TreeNode> childs;
        public TreeNode(NodeBase node)
        {
            curNode = node;
            childs = new List<TreeNode>();
        }
    }
    class Tree
    {
        public TreeNode root = null;
        public int nodeNum = 0;
        public TreeNode defaultNode = null;
        public TreeNode curNodeUpdate;
        public List<TreeNode> list;
        public Tree(NodeBase rootBase)
        {
            root = new TreeNode(rootBase);
            curNodeUpdate = root;
            nodeNum = 0;
            list = new List<TreeNode>();
            list.Add(root);
        }
        void ChangeCurNode(TreeNode target)
        {
            curNodeUpdate.curNode.Exit();
            curNodeUpdate = target;
            curNodeUpdate.curNode.Enter();
        }
        public void Run()
        {
            if(root==null)
            {
                Debug.LogError("无根节点！");
            }
            if(defaultNode==null)
            {
                Debug.LogError("无默认节点！");
            }
            if (curNodeUpdate.curNode.nodeKind != NodeKind.Jump && curNodeUpdate.curNode.active)
                curNodeUpdate.curNode.Exceute();


            if (curNodeUpdate.curNode.nodeKind == NodeKind.Jump)
            {
                if (curNodeUpdate.curNode.jumpToDefault)
                    ChangeCurNode(defaultNode);
                else
                    ChangeCurNode(list[curNodeUpdate.curNode.targetNode.id]);
            }
            else if (curNodeUpdate.curNode.nodeKind == NodeKind.Leave)
            {
                if (curNodeUpdate.curNode.DetectExitCondition())
                    ChangeCurNode(defaultNode);
            }
            else if (curNodeUpdate.curNode.nodeKind == NodeKind.Brancher || curNodeUpdate.curNode.nodeKind == NodeKind.Root)
            {
                if (curNodeUpdate.curNode.brancherKind == BrancherKind.Selector)
                {
                    bool flag = false;
                    if (curNodeUpdate.curNode.randExcute)
                    {
                        int n = curNodeUpdate.childs.Count;
                        int[] index = new int[n];

                        for (int i = 0; i < n; i++)
                            index[i] = i;
                        for (int i = 0; i < n; i++)
                        {
                            int a = Random.Range(0, n);
                            int b = Random.Range(0, n);
                            int tmp = index[a];
                            index[a] = index[b];
                            index[b] = tmp;
                        }
                        for (int i = 0; i < n; i++)
                        {
                            if (curNodeUpdate.childs[index[i]].curNode.DetectCondition())
                            {
                                if (!curNodeUpdate.childs[index[i]].curNode.active)
                                    continue;
                                ChangeCurNode(curNodeUpdate.childs[index[i]]);
                                flag = true;
                                break;
                            }
                        }
                    }
                    else
                    {
                        for (int i = 0; i < curNodeUpdate.childs.Count; i++)
                        {
                            if (curNodeUpdate.childs[i].curNode.DetectCondition())
                            {
                                if (!curNodeUpdate.childs[i].curNode.active)
                                    continue;
                                ChangeCurNode(curNodeUpdate.childs[i]);
                                flag = true;
                                break;
                            }
                        }
                    }
                    if(!flag)
                        ChangeCurNode(defaultNode);
                }
            }

        }
    }
    public NodeBase root;
    Tree tree = null;
    private void Start()
    {
        GenerateBehTree();
    }
    public void GenerateBehTree()
    {
        if (root.nodeKind != NodeKind.Root)
            return;
        if (tree != null)
            DestoryTree();
        tree = new Tree(root);
        root.id = tree.nodeNum;
        root.driver = this;
        tree.nodeNum++;
        tree.list.Add(tree.root);
        GenerateNode(tree.root);
    }
    TreeNode AddNode(NodeBase baseNode)
    {
        TreeNode treeNode = new TreeNode(baseNode);
        baseNode.id = tree.nodeNum;
        baseNode.driver = this;
        tree.nodeNum++;
        tree.list.Add(treeNode);
        return treeNode;
    }
    void GenerateNode(TreeNode p)
    {
        print(p.curNode.name);
        if (p.curNode.nodeKind == NodeKind.Leave || p.curNode.nodeKind == NodeKind.Jump)
        {
            p.childs = null;
            return;
        }
        if (p.curNode.isDefault && tree.defaultNode == null)
            tree.defaultNode = p;
        for (int i = 0; i < p.curNode.transform.childCount; i++)
        {
            NodeBase tmpNode = p.curNode.transform.GetChild(i).GetComponent<NodeBase>();
            if (tmpNode == null)
                continue;
            TreeNode tmpTreeNode = AddNode(tmpNode);
            p.childs.Add(tmpTreeNode);
            GenerateNode(tmpTreeNode);
        }
    }
    public void DestoryTree()
    {
        for(int i=0;i<tree.list.Count;i++)
            tree.list[i]=null;
        tree.list = null;
        tree.root=null;
        tree=null;
    }
    private void Update()
    {
        if(tree!=null)
            tree.Run();
    }
}}